using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;

namespace MIMP
{
    public class SpriteDisplay
    {
        private Vector2 origin;
        /// <summary>
        /// A Vector2 that stores the origin (upper left pixel) of the Hex.
        /// </summary>
        public Vector2 Origin
        {
            get { return origin; }
            set 
            { 
                origin = value;
                bounds = new Rectangle((int)origin.X, (int)origin.Y, (int)(sprite.Width * scale), (int)(sprite.Height * scale));
            }
        }
        private double scale;
        /// <summary>
        /// Factor by which to scale this Hex when drawing it.
        /// </summary>
        public double Scale
        {
            get { return scale; }
            set { 
                scale = value;
                bounds = new Rectangle((int)origin.X, (int)origin.Y, (int)(sprite.Width * scale), (int)(sprite.Height * scale));
            }
        }
        private Texture2D sprite;
        /// <summary>
        /// The Texture2D that is used to draw the Hex.
        /// </summary>
        public Texture2D Sprite
        {
            get { return sprite; }
            set 
            { 
                sprite = value;
                bounds = new Rectangle((int)origin.X, (int)origin.Y, (int)(sprite.Width * scale), (int)(sprite.Height * scale));
            }
        }
        private Rectangle bounds;
        /// <summary>
        /// Gets the bounds of the SpriteDisplay. Can not be set directly--to modify, change Origin, Scale, or Sprite.
        /// </summary>
        public Rectangle Bounds
        {
            get { return bounds; }
        }
        private Color[] spriteData;

        private bool isMouseOver;
        /// <summary>
        /// True if the mouse cursor is hovering over this HexDisplay *and* IsClickable is true, false otherwise. 
        /// To set this value, use the SetIsMouseOver method.
        /// </summary>
        public bool IsMouseOver
        {
            get { return isClickable && isMouseOver; }
        }
        private bool isClickable;
        /// <summary>
        /// Indicates whether the user can interact with this SpriteDisplay. If false, IsMouseOver will never be true.
        /// </summary>
        public bool IsClickable
        {
            get { return isClickable; }
            set { isClickable = value; }
        }
        private Keys key;
        /// <summary>
        /// The keyboard key associated with this SpriteDisplay. 
        /// </summary>
        public Keys ShortcutKey
        {
            get { return key; }
            set { key = value; }
        }
        private bool visible;
        /// <summary>
        /// True if the SpriteDisplay should be drawn, false otherwise.
        /// </summary>
        public bool IsVisible
        {
            get { return visible; }
            set { visible = value; }
        }
        /// <summary>
        /// Constructs a new SpriteDisplay object.
        /// </summary>
        /// <param name="x">The x coordinate of the origin of the Hex.</param>
        /// <param name="y">The y coordinate of the origin of the Hex.</param>
        /// <param name="scale">The factor by which to scale the Hex.</param>
        /// <param name="key">The keyboard key associated with this SpriteDisplay.</param>
        /// <param name="sprite">The Texture2D used to draw the Hex.</param>
        /// <param name="isClickable">True if the SpriteDisplay can be clicked on by the user.</param>
        /// <param name="isVisible">True if the SpriteDisplay should be drawn.</param>
        public SpriteDisplay(float x, float y, float scale, Keys key, Texture2D sprite, bool isVisible, bool isClickable)
        {
            this.scale = scale;
            this.origin = new Vector2(x, y);
            this.isMouseOver = false;
            this.isClickable = true;
            this.sprite = sprite;
            this.key = key;
            this.spriteData = new Color[sprite.Width * sprite.Height];
            this.sprite.GetData<Color>(this.spriteData);
            this.bounds = new Rectangle((int)origin.X, (int)origin.Y, (int)(sprite.Width * scale), (int)(sprite.Height * scale));
            this.visible = isVisible;
            this.isClickable = isClickable;
        }

        public SpriteDisplay(float x, float y, float scale, Texture2D sprite)
            : this(x,y,scale,Keys.D9,sprite)
        { }

        public SpriteDisplay(float x, float y, float scale, Keys key, Texture2D sprite)
            : this(x,y,scale,key,sprite,true,true)
        { }

        /// <summary>
        /// Sets the IsMouseOver property. Uses the cursor location in the given 
        /// MouseState to determine if the cursor is hovering over the SpriteDisplay.
        /// </summary>
        /// <param name="state">The current mouse state; used to determine the cursor location.</param>
        public void SetIsMouseOver(MouseState state)
        {
            bool inBoundingBox = state.X >= origin.X && state.X < origin.X + sprite.Width &&
                state.Y >= origin.Y && state.Y < origin.Y + sprite.Height;

            Color c = Color.White;
            if (inBoundingBox)
            {
                int x = state.X - (int)origin.X;
                int y = state.Y - (int)origin.Y;
                c = spriteData[(x + y * sprite.Width)];
            }
            isMouseOver = inBoundingBox && c.A > 20;
        }
        /// <summary>
        /// Checks if the whole Sprite is displayed within the (inclusive) bounds of the given Rectangle.
        /// </summary>
        /// <param name="bounds">The Rectangle to check the Sprite's location against.</param>
        /// <returns>True if all the texels of the Sprite are located inside the bounds of the given Rectangle.</returns>
        public bool IsInRectangle(Rectangle bounds)
        {
            return origin.X >= bounds.Left && origin.X + sprite.Width < bounds.Right &&
                origin.Y >= bounds.Top && origin.Y + sprite.Height < bounds.Bottom;
        }
        /// <summary>
        /// Searches each pixel in this SpriteDisplay's sprite and replaces all occurances of one Color
        /// with another Color.
        /// </summary>
        /// <param name="toReplace">The Color to search for in the sprite.</param>
        /// <param name="newColor">The Color to replace the found color with.</param>
        public void ReplaceColorInSprite(Color toReplace, Color newColor)
        {
            for(int i=0;i<spriteData.Length;i++)
            {
                if (spriteData[i].Equals(toReplace))
                {
                    spriteData[i] = newColor;
                }
            }
            sprite.SetData<Color>(spriteData);
        }
    }
}
